/*
 * Copyright (c) 2006-2024, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2024-12-31     RT-Thread    first version
 */

#include <rtthread.h>

#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
#include <stdio.h>
#include "bsp_can.h"
#include "can.h"
#include "gpio.h"
#include "usart.h"
#include "j1939.h"
#include "j1939_config.h"
#include "set_frameInfo.h"
#include "command_frame.h"
#include <string.h>

uint8_t buf[] = {0x01, 0x01, 0x02, 0x03, 0x04, 0x05, 0x66, 0x77};
uint8_t TxData[8] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88};
static rt_timer_t timer1;
static rt_timer_t timer2;

rt_bool_t boot_flag = RT_TRUE;

/* 定时器1超时函数 */
static void timer_j1939(void *parameter)
{
    J1939_Poll();
    J1939_TP_Poll(Select_CAN_NODE_1, 100);
}


/* 定时器2超时函数 --- 控制模块心跳帧 */
static void timer_TICK_MSG(void *parameter)
{
    j1939_TICK_MSG_AOC();
}

static ReceiveInfo recvinfo;
static struct YC_YX_MSG1 YC_YX1;
static struct YC_YX_MSG2 YC_YX2;

void my_can1_rx_callback(const j1939_uint32_t  id, const j1939_uint8_t* buf, const j1939_uint32_t  buf_len)
{
    printf("rx_callback begin\r\n");
    J1939_MESSAGE _msg;


    if(J1939_Read_Message( &_msg, Select_CAN_NODE_1) == RC_SUCCESS)
    {
        printf("_msg.j1939_pid.PGN = %#x\n", _msg.j1939_pid.PGN);

        //接收到遥信遥测数据帧1
        if(_msg.j1939_pid.PGN == 0x002000)
        {
            printf("接收到遥信遥测数据帧1\n");
            printf("Received from CAN1: ID = %#lx, Data Length = %lu, Data: ", id, buf_len);
            printf("Received from CAN1: PGN = %#x", _msg.j1939_pid.PGN);

            for (j1939_uint32_t  i = 0; i < buf_len; i++) {
                printf("%02X ", buf[i]);
            }
            printf("\n");

            YC_YX1.state.work_state = (buf[0] >> 6) & 0x03;
            YC_YX1.state.warn_state = (buf[0] >> 5) & 0x01;
            YC_YX1.state.fault_state = (buf[0] >> 4) & 0x01;
            YC_YX1.state.group_mode = (buf[0] >> 3) & 0x03;
            YC_YX1.state.received= (buf[0] >> 0) & 0x07;
            YC_YX1.warn_fault.ac_in_fault = (buf[1] >> 7) & 0x01;
            YC_YX1.warn_fault.dc_out_over_fault = (buf[1] >> 6) & 0x01;
            YC_YX1.warn_fault.dc_out_under_fault = (buf[1] >> 5) & 0x01;
            YC_YX1.warn_fault.temp_over_fault = (buf[1] >> 4) & 0x01;
            YC_YX1.warn_fault.dc_out_sc_fault = (buf[1] >> 3) & 0x01;
            YC_YX1.warn_fault.fan_fault = (buf[1] >> 2) & 0x01;
            YC_YX1.warn_fault.vent_fault = (buf[1] >> 1) & 0x01;
            YC_YX1.warn_fault.another_fault = (buf[1] >> 0) & 0x01;
            YC_YX1.dc_out_voc = ((j1939_uint16_t)buf[3] << 8) | buf[2];
            YC_YX1.dc_out_cur = ((j1939_uint16_t)buf[5] << 8) | buf[4];
            YC_YX1.group_number = buf[6];

            printf("工作状态：%#x\n", YC_YX1.state.work_state);
            printf("告警状态：%#x\n", YC_YX1.state.warn_state);
            printf("故障状态%#x\n", YC_YX1.state.fault_state);
            printf("分组模式：%#x\n", YC_YX1.state.group_mode);
            printf("预留：%#x\n", YC_YX1.state.received);
            printf("交流输入故障:%#x\n", YC_YX1.warn_fault.ac_in_fault);
            printf("直流输出过压故障:%#x\n", YC_YX1.warn_fault.dc_out_over_fault);
            printf("直流输出欠压故障:%#x\n", YC_YX1.warn_fault.dc_out_under_fault);
            printf("过温故障:%#x\n", YC_YX1.warn_fault.dc_out_under_fault);
            printf("直流输出短路故障:%#x\n", YC_YX1.warn_fault.dc_out_sc_fault);
            printf("风扇故障:%#x\n", YC_YX1.warn_fault.fan_fault);
            printf("泄放故障:%#x\n", YC_YX1.warn_fault.vent_fault);
            printf("其他故障:%#x\n", YC_YX1.warn_fault.another_fault);
            printf("直流输出电压:%#x\n", YC_YX1.dc_out_voc);
            printf("直流输出电流:%#x\n", YC_YX1.dc_out_cur);
            printf("当前组号:%#x\n", YC_YX1.group_number);
        }

        if(_msg.j1939_pid.PGN == 0x002100)
        {
            printf("接收到遥信遥测数据帧2\n");
            printf("Received from CAN1: ID = %#lx, Data Length = %lu, Data: ", id, buf_len);
            printf("Received from CAN1: PGN = %#x", _msg.j1939_pid.PGN);

            for (j1939_uint32_t  i = 0; i < buf_len; i++) {
                printf("%02X ", buf[i]);
            }
            printf("\n");

            YC_YX2.alarm_state.over_temp_warning = (buf[1] >> 7) & 0x01;
            YC_YX2.alarm_state.output_overcurrent_warning = (buf[1] >> 6) & 0x01;
            YC_YX2.alarm_state.input_over_voltage_warning = (buf[1] >> 5) & 0x01;
            YC_YX2.alarm_state.input_under_voltage_warning = (buf[1] >> 4) & 0x01;
            YC_YX2.alarm_state.input_phase_loss_warning = (buf[1] >> 3) & 0x01;
            YC_YX2.alarm_state.communication_fault = (buf[1] >> 2) & 0x01;
            YC_YX2.alarm_state.start_failure = (buf[1] >> 1) & 0x01;
            YC_YX2.alarm_state.shutdown_failure = (buf[1] >> 0) & 0x01;;
            YC_YX2.alarm_state.module_address_error = (buf[0] >> 7) & 0x01;
            YC_YX2.alarm_state.received = 0;

            printf("过温告警：%#x\n", YC_YX2.alarm_state.over_temp_warning);
            printf("输出过流告警：%#x\n", YC_YX2.alarm_state.output_overcurrent_warning);
            printf("输入过压告警：%#x\n", YC_YX2.alarm_state.input_over_voltage_warning);
            printf("输入欠压告警：%#x\n", YC_YX2.alarm_state.input_under_voltage_warning);
            printf("输入缺相告警：%#x\n", YC_YX2.alarm_state.input_phase_loss_warning);
            printf("通信故障：%#x\n", YC_YX2.alarm_state.communication_fault);
            printf("启动失败：%#x\n", YC_YX2.alarm_state.start_failure);
            printf("关机失败：%#x\n", YC_YX2.alarm_state.shutdown_failure);
            printf("充电模块地址异常故障：%#x\n", YC_YX2.alarm_state.module_address_error);
            printf("预留：%#x\n", YC_YX2.alarm_state.received);
        }

        //接收到遥控应答帧
        if(_msg.j1939_pid.PGN == 0x600)
        {
            printf("接收到遥控应答帧（动态分组模式下）\n");
            printf("Received from CAN1: ID = %#lx, Data Length = %lu, Data: ", id, buf_len);

            for (j1939_uint32_t  i = 0; i < buf_len; i++) {
                printf("%02X ", buf[i]);
            }
            printf("\n");
            
            recvinfo.YD_control_byte.success_flag = (buf[0] >> 7) & 0x01;
            recvinfo.YD_control_byte.main_contact_status = (buf[0] >> 6) & 0x01;
            recvinfo.YD_control_byte.power_distribution_contact_status = (buf[0] >> 5) & 0x01;
            recvinfo.YD_control_byte.voltage_output_range = (buf[0] >> 4) & 0x01;
            recvinfo.YD_control_byte.operation_instructions = buf[0] & 0x0F;
            recvinfo.group_encoding = buf[1];
            recvinfo.set_vdc = ((j1939_uint16_t)buf[3] << 8) | buf[2];
            recvinfo.set_current = ((j1939_uint16_t)buf[5] << 8) | buf[4];
            recvinfo.battery_vdc = ((j1939_uint16_t)buf[7] << 8) | buf[6]; 

            printf("成功标识：%#x\n", recvinfo.YD_control_byte.success_flag);
            printf("充电回路主接触器状态：%#x\n", recvinfo.YD_control_byte.main_contact_status);
            printf("功率分配回路接触器状态：%#x\n", recvinfo.YD_control_byte.power_distribution_contact_status);
            printf("电压输出范围选择：%#x\n", recvinfo.YD_control_byte.voltage_output_range);
            printf("操作指令：%#x\n", recvinfo.YD_control_byte.operation_instructions);
            printf("分组编码：%#x\n", recvinfo.group_encoding);
            printf("给定电压：%#x\n", recvinfo.set_vdc);
            printf("给定电流：%#x\n", recvinfo.set_current);
            printf("电池电压：%#x\n", recvinfo.battery_vdc);
        }

        //接收到分组设置应答帧
        if(_msg.j1939_pid.PGN == 0x400)
        {
            printf("接收到分组设置应答帧\n");
        }
        //接收到定值设置应答帧
        if(_msg.j1939_pid.PGN == 0x8100)
        {
            printf("接收到定值设置应答帧\n");
        }
    }
    if(J1939_Read_Message( (&_msg+1), Select_CAN_NODE_1) == RC_SUCCESS)
    {
        printf("PDU22\r\n");
        /***********处理接受PDU2格式数据*************/
        if(_msg.j1939_pid.PDUFormat >= 240 && _msg.j1939_pid.PDUFormat <= 255)
        {
            printf("PDU2\r\n");
        }
    }

    printf("\n");

}



int main(void)
{
    MX_GPIO_Init();
    MX_CAN1_Init();
    MX_USART1_UART_Init();
    bsp_can_init(can1_port);
    bsp_can_start(can1_port);
    printf("can_init success!\r\n");

    //注册添加回调函数
    bsp_can_add_rx_callback(Select_CAN_NODE_1, my_can1_rx_callback);

    J1939_Config_Init(bsp_can_send_message, bsp_can_add_rx_callback);

    printf("j1939 init success!\r\n");

    /* 创建定时器1  周期定时器 */
    timer1 = rt_timer_create("timer_j1939", timer_j1939,
                             RT_NULL, 5,
                             RT_TIMER_FLAG_PERIODIC);
    /* 启动定时器1 */
    if (timer1 != RT_NULL)
        rt_timer_start(timer1);
    else {
        printf("timer1 init failed..\n");
    }

    /* 创建定时器2 周期定时器 --- 控制模块心跳帧 */
    timer2 = rt_timer_create("timer_TICK_MSG", timer_TICK_MSG,
                             RT_NULL, 2000, 
                             RT_TIMER_FLAG_PERIODIC);
    /* 启动定时器2 */
    if (timer2 != RT_NULL)
        rt_timer_start(timer2);
    else {
        printf("timer2 init failed..\n");
    }                      

    //设置定值信息 (充电接口标识， 设备通信地址， 定值序号， 定值信息， 定值信息长度)
    SetFixVal_DYGroup(0, 0x80, 0x0D, 0x02, 1);
    //发送定值设置命令帧 [目标地址, PDU]
    if(j1939_SET_VALUECMD(&fix_val_CMD_DY, 0x80, 0x80) == SUCCESS)
        printf("j1939_SET_VALUECMD SUCCESS.\r\n");


    //设置分组信息(分组设置， 连续地址， 组号， 组数， 起始地址， 终止地址)
    group_set(1, 1, 1, 1, 0x80, 0x80);
    //发送分组设置帧（动态分组模式） [目标地址, PDU]
    if(j1939_GPCMD_DynamicGroup(&type_group_set, 0x80, 0x03) == SUCCESS)
        printf("j1939_GPCMD_DynamicGroup SUCCESS.\r\n");


    while(1)
    {
        //发送遥控命令帧（动态分组模式）
        if(boot_flag)
            j1939_GDCMD_DynamicGroup(0x80, 0x05, 0x02, 0x01); //目标地址, PDU, 快速开机，高电压段
        
        HAL_Delay(300);
    }


    return RT_EOK;
}






